﻿using System;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace PlainConcepts.WCF.Extensions.Cache
{
	/// <summary>
	/// This attribute is used for adding cache to and WCF operation
	/// </summary>
	[AttributeUsage(AttributeTargets.Method)]
	sealed public class UseCacheAttribute : Attribute, IOperationBehavior
	{
		private int _cacheDuration;

		/// <summary>
		/// Gets the number of seconds the response should be held in the cache.
		/// </summary>
		public int CacheDuration
		{
			get { return _cacheDuration; }
		}
	
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="cacheDuration">
		/// The number of seconds the response should be held in the cache.
		/// </param>
		public UseCacheAttribute(int cacheDuration)
		{
			_cacheDuration = cacheDuration >= 0 ? cacheDuration : 0;
		}

		#region IOperationBehavior Members

		/// <summary>
		/// Implementation for AddBindingParameters. An empty implementation is OK.
		/// </summary>
		/// <param name="operationDescription">Operation description</param>
		/// <param name="bindingParameters">Binding parameters</param>
		/// <remarks>
		/// <see cref="IOperationBehavior.ApplyDispatchBehavior"/>
		/// </remarks>
		public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
		{
		}

		/// <summary>
		/// Implementation for ApplyClientBehavior. An empty implementation is OK.
		/// </summary>
		/// <param name="operationDescription">Operation description</param>
		/// <param name="clientOperation">Client operation</param>
		/// <remarks>
		/// <see cref="IOperationBehavior.ApplyDispatchBehavior"/>
		/// </remarks>
		public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
		{
		}

		/// <summary>
		/// This method applies our operation invoker to the operation
		/// </summary>
		/// <param name="operationDescription">Operation description</param>
		/// <param name="dispatchOperation">Operation dispatch</param>
		/// <remarks>
		/// <see cref="IOperationBehavior.ApplyDispatchBehavior"/>
		/// </remarks>
		public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
		{
			dispatchOperation.Invoker = new CachedInvoker(dispatchOperation.Invoker, _cacheDuration, dispatchOperation.Name);
		}

		/// <summary>
		/// Implementation for Validate. An empty implementation is OK.
		/// </summary>
		/// <param name="operationDescription">Operation description</param>
		/// <remarks>
		/// <see cref="IOperationBehavior.Validate"/>
		/// </remarks>
		public void Validate(OperationDescription operationDescription)
		{
		}

		#endregion
	}
}
